package com.github.zy.rpc.session;

import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @version 1.0 created by zy on 2020/4/26 14:53
 */
@Component
public class NativeCacheSessionStorage implements SessionStorage {

    private final ConcurrentHashMap<String, List<Session>> cache = new ConcurrentHashMap<>();

    @Override
    public List<Session> findByModuleId(String moduleId) {
        return cache.get(moduleId);
    }

    @Override
    public Session findOne(String sessionId) {
        for (List<Session> sessions : cache.values()) {
            Optional<Session> optional = sessions.stream().filter(session -> session.getId().equals(sessionId)).findFirst();
            if (optional.isPresent()) {
                return optional.get();
            }
        }
        return null;
    }

    @Override
    public Map<String, List<Session>> findAll() {
        return cache;
    }

    @Override
    public void delete(String sessionId) {
        Set<String> removeModuleIds = new HashSet<>();
        for (List<Session> sessions : cache.values()) {
            Iterator<Session> iterator = sessions.iterator();
            while (iterator.hasNext()) {
                Session session = iterator.next();
                if (session.getId().equals(sessionId)) {
                    String moduleId = session.getModuleId();
                    iterator.remove();

                    //每次移除一个session都去判断下这个模块下是否已经没有了value,如果没有的话,就将key移除
                    if (CollectionUtils.isEmpty(cache.get(moduleId))) {
                        removeModuleIds.add(moduleId);
                    }
                }
            }
        }
        //完成后,去检测一次cache中是否有已经没有value的key
        removeNullValue(removeModuleIds);
    }


    @Override
    public void delete(Iterable<String> sessionIds) {
        Set<String> removeModuleIds = new HashSet<>();
        for (List<Session> sessions : cache.values()) {
            Iterator<Session> iterator = sessions.iterator();
            while (iterator.hasNext()) {
                Session session = iterator.next();
                String moduleId = session.getModuleId();
                sessionIds.forEach(sessionId -> {
                    if (session.getId().equals(sessionId)) {
                        iterator.remove();

                        if (CollectionUtils.isEmpty(cache.get(moduleId))) {
                            removeModuleIds.add(moduleId);
                        }
                    }
                });
            }
        }

        removeNullValue(removeModuleIds);
    }


    @Override
    public void save(Session session) {
        String moduleId = session.getModuleId();
        if (!cache.containsKey(moduleId)) {
            List<Session> sessions = new ArrayList<>();
            sessions.add(session);
            cache.put(moduleId, sessions);
        } else {
            List<Session> sessions = cache.get(moduleId);
            sessions.add(session);
        }
    }

    @Override
    public void save(Iterable<Session> sessions) {
        sessions.forEach(session -> {
            String moduleId = session.getModuleId();
            if (cache.containsKey(moduleId)) {
                cache.get(moduleId).add(session);
            } else {
                List<Session> sessionList = new ArrayList<>();
                sessionList.add(session);
                cache.put(moduleId, sessionList);
            }
        });
    }


    /**
     * 移除空value的 key
     */
    private void removeNullValue(Set<String> removeModuleIds) {
        removeModuleIds.forEach(id -> cache.remove(id));
    }
}
